package algo.Common;


import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector; 


import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.*;

import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import vn.webapp.model.BusyTeachers;
import vn.webapp.model.BusyToTeachers;
import vn.webapp.model.Classes;
import vn.webapp.model.Courses;
import vn.webapp.model.Coursing;
import vn.webapp.model.Teachers;
import vn.webapp.model.TeachersToBusy;

public class Data {

	/**
	 * @param args
	 */
	
	Vector<Course>	_courses;
	Vector<ClassTT> _classes;
	Vector<Instructor> _instructors;
	
	public Vector<Course> getCourses(){ return _courses;}
	public Vector<ClassTT> getClasses(){ return _classes;}
	
	private ClassTT findClass(String classID){
		for(int i = 0; i < _classes.size(); i++){
			String id = (_classes.elementAt(i)).getID();
			if(id.equals(classID)) 
				return _classes.elementAt(i);
		}
		return null;
	}
	private Instructor addInstructor(int id, String name){
		Instructor I = null;
		for(int i = 0; i < _instructors.size(); i++){
			if(_instructors.elementAt(i).getID() == id){
				I = _instructors.elementAt(i);
				break;
			}
		}
		if(I == null)
			I = new Instructor(id,name);
		_instructors.add(I);
		return I;		
	}
	public ClassTT getClass(int idx){
		return _classes.elementAt(idx);
	}
	public Vector<Course> getCoursesOfClass(ClassTT cls){
		Vector<Course> courses = new Vector<Course>();
		for(int i = 0; i < _courses.size(); i++){
			Course c = _courses.elementAt(i);
			Vector<ClassTT> cla = c.getClasses();
			for(int j = 0; j < cla.size(); j++){
				if(cla.elementAt(j) == cls)
					courses.add(c);
			}
		}
		return courses;
	}
	public boolean conflict(Course c1, Course c2){
		Vector<ClassTT> cls1 = c1.getClasses();
		Vector<ClassTT> cls2 = c2.getClasses();
		for(int i = 0; i < cls1.size();i++){
			if(cls2.contains(cls1.elementAt(i))) return true;
		}
		for(int i = 0; i < cls2.size();i++){
			if(cls1.contains(cls2.elementAt(i))) return true;
		}	
		if(c1.getInstructor() == c2.getInstructor()) return true;
		return false;
	}
	
	String getValue(Node nod){
		Element e_nod = (Element)nod;
		NodeList l1 = e_nod.getChildNodes();
		String v = l1.item(0).getNodeValue();
		return v;
	}
	public void readData(String filename){
            try{
                    //System.out.println("try");
                    _courses = new Vector<Course>();
                    _classes = new Vector<ClassTT>();
                    _instructors = new Vector<Instructor>();

                    DocumentBuilderFactory docBF = DocumentBuilderFactory.newInstance();
                    DocumentBuilder docB = docBF.newDocumentBuilder();
                    Document doc = docB.parse(new File(filename));
                    doc.getDocumentElement().normalize();
                    //System.out.println("Root element of the document is " + doc.getDocumentElement().getNodeName());


                    NodeList lstInstructors = doc.getElementsByTagName("instructorsList");
                    Node nod_lstInstructors = lstInstructors.item(0);
                    Element e_lstInstructors = (Element)nod_lstInstructors;

                    lstInstructors = e_lstInstructors.getElementsByTagName("instructor");
                    //System.out.println("lstInstructors.length = " + lstInstructors.getLength());
                    for(int i = 0; i < lstInstructors.getLength(); i++){
                            Node c = lstInstructors.item(i);
                            //System.out.println("Process node " + i + " c = " + c.getNodeName());
                            if(c.getNodeType() == Node.ELEMENT_NODE){
                                    Element e = (Element)c;
                                    NodeList l = e.getElementsByTagName("name");
                                    Node nod = l.item(0);
                                    Element e_nod = (Element)nod;
                                    l = e_nod.getChildNodes();
                                    //System.out.println("Get instructor name = " + l.item(0).getNodeValue());
                                    String instructor_name = l.item(0).getNodeValue();

                                    l = e.getElementsByTagName("id");
                                    nod = l.item(0);
                                    e_nod = (Element)nod;
                                    l = e_nod.getChildNodes();
                                    //System.out.println("Get instructor id = " + l.item(0).getNodeValue());
                                    int instructor_id = Integer.valueOf(l.item(0).getNodeValue());
                                    Vector<DaySlot> dayslots = new Vector<DaySlot>();

                                    NodeList lstBusy = e.getElementsByTagName("busy");
                                    //System.out.println("lstBusy.size = " + lstBusy.getLength());
                                    for(int j = 0; j < lstBusy.getLength(); j++){
                                            Node ci = lstBusy.item(j);
                                            e = (Element)ci;
                                            l = e.getElementsByTagName("day");
                                            nod = l.item(0);
                                            //System.out.println(nod.getNodeName() + "\t" + getValue(nod));
                                            int d = Integer.valueOf(getValue(nod));
                                            l = e.getElementsByTagName("slot");
                                            nod = l.item(0);
                                            int sl = Integer.valueOf(getValue(nod));
                                            dayslots.add(new DaySlot(d,sl));
                                            //System.out.println("day = " + d + " slot = " + sl);
                                    }
                                    //System.out.println("start addInstructor " + instructor_id);
                                    Instructor I = addInstructor(instructor_id,instructor_name);
                                    I.setBusy(dayslots);
                                    //System.out.println("start addInstructor " + instructor_id + " --> OK, _instructors.size = " + _instructors.size());
                            }
                    }
                    //System.out.println("read instructors --> OK, start  printing");
                    for(int i = 0; i < _instructors.size(); i++){
                            Instructor I = _instructors.elementAt(i);
                            //I.print();
                    }

                    //assert(false);

                    NodeList lstCourses = doc.getElementsByTagName("course");
                    //System.out.println("Number of courses = " + lstCourses.getLength());
                    for(int i = 0; i < lstCourses.getLength(); i++){
                            //System.out.println("i = " + i);
                            Node c = lstCourses.item(i);
                            //if(c == null) System.out.println("c = NULL");
                            if(c.getNodeType() == Node.ELEMENT_NODE){
                                    Element e = (Element)c;
                                    NodeList l = e.getElementsByTagName("name");
                                    Node nod = l.item(0);
                                    Element e_nod = (Element)nod;
                                    l = e_nod.getChildNodes();
                                    //System.out.println("Get course name = " + l.item(0).getNodeValue());
                                    String course_name = l.item(0).getNodeValue();

                                    l = e.getElementsByTagName("id");
                                    nod = l.item(0);
                                    e_nod = (Element)nod;
                                    l = e_nod.getChildNodes();
                                    //System.out.println("Get course id = " + l.item(0).getNodeValue());
                                    String course_id = l.item(0).getNodeValue();


                                    l = e.getElementsByTagName("instructor");
                                    nod = l.item(0);
                                    e_nod = (Element)nod;
                                    l = e_nod.getChildNodes();
                                    //System.out.println("Get course instructor = " + l.item(0).getNodeValue());
                                    int instructor_id = Integer.valueOf(l.item(0).getNodeValue());

                                    l = e.getElementsByTagName("nbrSlots");
                                    nod = l.item(0);
                                    e_nod = (Element)nod;
                                    l = e_nod.getChildNodes();
                                    //System.out.println("Get course nbSlots = " + l.item(0).getNodeValue());
                                    int nbSlots = Integer.valueOf(l.item(0).getNodeValue());

                                    l = e.getElementsByTagName("classList");
                                    //System.out.println("classes size = " + l.getLength());
                                    nod = l.item(0);
                                    //System.out.println("nod = " + nod.getNodeName() + " nod.value = " + nod.getNodeValue());
                                    e_nod = (Element)nod;
                                    //l = e_nod.getChildNodes();
                                    l = e_nod.getElementsByTagName("class");
                                    //System.out.println("classes size = " + l.getLength());

                                    Vector<ClassTT> classes = new Vector<ClassTT>();

                                    //System.out.println("classes size = " + l.getLength());
                                    for(int j = 0; j < l.getLength(); j++){
                                            Node clsNod = l.item(j);
                                            //System.out.println("clsNod = " + clsNod.getNodeName() + " clsNod.value = " + clsNod.getNodeValue());
                                            //NodeList l1 = ((Element)clsNod).getElementsByTagName("class");
                                            //nod = l1.item(0);
                                            //System.out.println("l1.sz = " + l1.getLength());

                                            e_nod = (Element)clsNod;
                                            NodeList l1 = e_nod.getChildNodes();
                                            String cls_id = l1.item(0).getNodeValue();
                                            //String cls_id = nod.getNodeValue();
                                            //System.out.print("j = " + j + " class = " + cls_id + " ");
                                            ClassTT cls = findClass(cls_id);
                                            if(cls == null){
                                                    cls = new ClassTT(cls_id);
                                                    _classes.add(cls);
                                            }
                                            //ClassTT cls = new ClassTT(cls_id);
                                            classes.add(cls);

                                            //if(!checkExists(cls_id))
                                                    //_classes.add(cls);
                                    }
                                    //System.out.println("classes = " + classes.size());

                                    Instructor I = addInstructor(instructor_id,"noname");
                                    _courses.add(new Course(course_id, course_name, I,nbSlots,classes));
                                    //System.out.println("OK");
                            }
                    }


                    for(int i = 0; i < _courses.size(); i++){
                            Course c = _courses.elementAt(i);

                            Vector<ClassTT> classes = (Vector<ClassTT>)c.getClasses();
                            Iterator it = classes.iterator();
                            String s = "";
                            while(it.hasNext()){
                                    ClassTT cls = (ClassTT)it.next();
                                    s = s + cls.getID() + "-";
                            }
                            //System.out.println(c.getID() + " | " + c.getName() + " | " + c.getInstructor().getName() + " | " + c.getNbrSlots() + " | " + s);
                    }
                    //for(int i = 0; i < _classes.size(); i++)
                            //System.out.println("Class: " + _classes.elementAt(i).getID());

                    //for(int i = 0; i < _courses.size(); i++){
                            //Course c = _courses.elementAt(i);
                            //c.print();
                    //}

            }catch(SAXParseException err){
                    System.out.println("Parsing error at line " + err.getLineNumber() + ", uri = " + err.getSystemId());
                    System.out.println("error message is: " + err.getMessage());
            }catch(SAXException e){
                    Exception x = e.getException();
                    ((x == null)? e : x).printStackTrace();			
            }catch(Throwable t){
                    t.printStackTrace();
            }
	}
	
	public int getMinDay(){ return 2;}
	public int getMaxDay(){ return 6;}
	public int getMinSlot(){ return 1;}
	public int getMaxSlot(){ return 6;}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("Data");
	}
        
        public void formatData(List<Classes> __classes, List<Courses> __courses, Set<TeachersToBusy> __teachers, Set<Coursing> __coursings)
        {
            List<Classes> ___classes___ = __classes;
            List<Courses> ___courses___ = __courses;
            Set<TeachersToBusy> ___teachers___ = __teachers;
            Set<Coursing> ___coursings___ = __coursings;
            // Format teachers - instructors:
            
            
            Vector<Instructor> _instructors_ = new Vector<Instructor>();
            for(TeachersToBusy teacher : __teachers)
            {
                Instructor ___instructor = new Instructor(teacher.getTeacher_id(), teacher.getName());
                
                if(teacher.getBusyToTeachers() != null)
                {
                    Vector<DaySlot> dayslots = new Vector<DaySlot>();
                    for(BusyToTeachers bstt : teacher.getBusyToTeachers())
                    {
                        dayslots.add(new DaySlot(bstt.getDay(),bstt.getSlot()));
                    }
                    ___instructor.setBusy(dayslots);
                }
                _instructors_.addElement(___instructor);
                //_instructors.add(index, ___instructor);
                
            }
            _instructors = _instructors_;
            Vector<ClassTT> _classes_ = new Vector<ClassTT>();
            for(Classes clas : __classes)
            {
                ClassTT _____class_ = new ClassTT(clas.getName());
                _classes_.addElement(_____class_);
            }
            _classes = _classes_;
            
            // Course formating 
            String sz_CourseId = "";
            String sz_CourseName = "";
            Courses oCourses = new Courses();
            Vector<Course> _courses_ = new Vector<Course>();
            for(Coursing course : __coursings)
            {
                sz_CourseId = Integer.toString(course.getCourse_id());
                oCourses = course.getCourses();
                Instructor ___instructors = null;
                // Handling classes
                for (Instructor _inst : _instructors_ )
                {
                    if(_inst._id == course.getTeacher_id())
                    {
                        ___instructors = _inst;
                    }
                }
                
                Vector<ClassTT> __classes__ = new Vector<ClassTT>();
                for(Classes _class_ : course.getClasses())
                {
                    ClassTT _____class = new ClassTT(_class_.getName());
                    __classes__.addElement(_____class);
                }
                
                Course ____course_ = new Course(sz_CourseId, oCourses.getName(), ___instructors, oCourses.getCredits(), __classes__);
                _courses_.addElement(____course_);
            }       
            _courses = _courses_;
            
            System.out.println("Data");
        }
        
    public static void v_fBuildData(List<Classes> __classes, List<Courses> __courses, Set<TeachersToBusy> __teachers, Set<Coursing> __coursings)
    {
        try {
 
                List<Classes> ___classes___ = __classes;
                List<Courses> ___courses___ = __courses;
                Set<TeachersToBusy> ___teachers___ = __teachers;
                Set<Coursing> ___coursings___ = __coursings;
            
		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
                    
                /**
                 * root elements - timetabling
                 */
		Document doc = docBuilder.newDocument();
		Element rootElement = doc.createElement("timetabling");
		doc.appendChild(rootElement);
 
                /**
                 * second leaf elements - instructorsList
                 */
                Element instructorsListElement = doc.createElement("instructorsList");
		rootElement.appendChild(instructorsListElement);
                
                if(!__teachers.isEmpty())
                {
                    for(TeachersToBusy teacherBusy : __teachers){
                        // third elements - instructor
                        Element instructorElement = doc.createElement("instructor");
                        instructorsListElement.appendChild(instructorElement);

                        // instructor id elements
                        Element instructorId = doc.createElement("id");
                        instructorId.appendChild(doc.createTextNode(Integer.toString(teacherBusy.getTeacher_id())));
                        instructorElement.appendChild(instructorId);

                        // instructor name elements
                        Element instructorName = doc.createElement("name");
                        instructorName.appendChild(doc.createTextNode(teacherBusy.getName()));
                        instructorElement.appendChild(instructorName);

                        if(!teacherBusy.getBusyToTeachers().isEmpty())
                        {
                            for(BusyToTeachers busyEle : teacherBusy.getBusyToTeachers())
                            {
                                // fourth elements - instructor busy elements
                                Element instructorBusy = doc.createElement("busy");
                                instructorElement.appendChild(instructorBusy);

                                Element instructorBusyDay = doc.createElement("day");
                                instructorBusyDay.appendChild(doc.createTextNode(Integer.toString(busyEle.getDay())));
                                instructorBusy.appendChild(instructorBusyDay);

                                Element instructorBusySlot = doc.createElement("slot");
                                instructorBusySlot.appendChild(doc.createTextNode(Integer.toString(busyEle.getSlot())));
                                instructorBusy.appendChild(instructorBusySlot);
                            }
                        }
                    }
                }
                /**
                 * second leaf elements - coursesList
                 */
                Element coursesListElement = doc.createElement("coursesList");
		rootElement.appendChild(coursesListElement);
                
                if(!__coursings.isEmpty())
                {
                    for(Coursing course : __coursings){
                        // third elements - course
                        Element courseElement = doc.createElement("course");
                        coursesListElement.appendChild(courseElement);

                        // course id elements
                        Element courseId = doc.createElement("id");
                        courseId.appendChild(doc.createTextNode(Integer.toString(course.getCourse_id())));
                        courseElement.appendChild(courseId);

                        // course name elements
                        Element courseName = doc.createElement("name");
                        courseName.appendChild(doc.createTextNode(course.getCourses().getName()));
                        courseElement.appendChild(courseName);
                        
                        Element courseInstructor = doc.createElement("instructor");
                        courseInstructor.appendChild(doc.createTextNode(Integer.toString(course.getTeacher_id())));
                        courseElement.appendChild(courseInstructor);

                        // course name elements
                        Element courseNbrSlots = doc.createElement("nbrSlots");
                        courseNbrSlots.appendChild(doc.createTextNode(Integer.toString(course.getCourses().getCredits())));
                        courseElement.appendChild(courseNbrSlots);


                        // fourth elements - classList elements
                        Element courseClassList= doc.createElement("classList");
                        courseElement.appendChild(courseClassList);
                        
                        if(!course.getClasses().isEmpty())
                        {
                            for(Classes _class : course.getClasses())
                            {
                                Element courseClassListClass = doc.createElement("class");
                                courseClassListClass.appendChild(doc.createTextNode(_class.getCode()));
                                courseClassList.appendChild(courseClassListClass);
                            }
                        }
                    }
                }
		// write the content into xml file
		TransformerFactory transformerFactory = TransformerFactory.newInstance();
		Transformer transformer = transformerFactory.newTransformer();
		DOMSource source = new DOMSource(doc);
		StreamResult result = new StreamResult(new File("C:\\Data\\file.xml"));
 
		// Output to console for testing
		// StreamResult result = new StreamResult(System.out);
 
		transformer.transform(source, result);
 
 
	  } catch (ParserConfigurationException pce) {
		pce.printStackTrace();
	  } catch (TransformerException tfe) {
		tfe.printStackTrace();
	  }
    }
}
